package util;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.List;

import javax.servlet.ServletContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import entity.Configure;
import entity.Video;
import entity.VideoState;
import service.ConfigureService;
import service.VideoService;
import service.VideoStateService;
import service.impl.ConfigureServiceImpl;

/**
 * 视频截取缩略图线程
 *
 */
public class VideoThumbnailThread extends Thread {

	/**
	 * 在写多线程的时候，使用@Autowired或者@Resource注解注入的时候，报NullException。
	 * 问题：多线程中无法共享主线程中的bean。
	 * 解决：手动获取bean ，编写工具类SpringContextUtils 
	 */
	
	//使用：@Component、@Controller、@Service、@Repository注解， 扫描的组件默认别名为”类名首字母小写”。
	ConfigureService configureService = (ConfigureService) SpringContextUtils.getSpringBean("configureServiceImpl"); //此处为什么小写
	VideoService videoService = (VideoService) SpringContextUtils.getSpringBean("videoServiceImpl"); 
	VideoStateService videoStateService = (VideoStateService) SpringContextUtils.getSpringBean("videoStateServiceImpl"); 
	
	private ServletContext servletContext;

	@Override
	public void run() {
		// 捕获异常，防止截取出错
		try {
			System.out.println("截取缩略图-线程开启");
			int order = 2;  //命令，即video中，videoState表示的值，2为等待截图
			WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
			System.out.println(configureService);
			
			Configure thumbnail_ss_cfg = configureService.findSingle("thumbnail_ss"); //获取截图为何时开始，此数值为FFmpeg中的命令行数值
			Configure folder_thumbernail_cfg = configureService.findSingle("folder_thumbnail"); //存放缩略图的文件路径。
			
			
			String realThumbnailDir = servletContext.getRealPath("/").replace('\\', '/') + folder_thumbernail_cfg.getVal(); //获取存放缩略图的完整路径

			File realThumbnailDirFile = new File(realThumbnailDir);  
			if(!realThumbnailDirFile.exists() && !realThumbnailDirFile.isDirectory()) { 			//检查是否存在此路径，否则创建
				realThumbnailDirFile.mkdirs();
			}
			
			while(true) {
				//获取数据库中，等待截图的视频集合，由于是在服务器方进行转码，不需要客户的信息，全部的信息进行截取
				List<Video> videoList = videoService.findByState(order);
				// 需要获取两个视频状态，
				// 一、如果是视频表示视频需要截图，截图过后，变成等待转码模式
				// 二、如果是rtmp表示为直播视频，那么视频不需要截图，直接完成截图和转码的过程变成完成模式。
				
				//遍历视频
				if(videoList != null) { 
					VideoState wait_coder = videoStateService.findById(order+1);
					VideoState finished_video = videoStateService.findById(order+2);
					for (Video video : videoList) {
						String realFileOriPath;    //源视频地址
						//如果不是直播的视频
						if(video.getIsLive() == 0) { //0为点播，1为直播
							realFileOriPath = servletContext.getRealPath("/").replace('\\', '/') + video.getOriUrl();
						} else {   //如果是直播，不需要获取项目的路径
							realFileOriPath = video.getUrl();
							String str[] = realFileOriPath.split(":");
							if(str[0].equals("rtmp") || str[0].equals("rtmpe") || str[0].equals("rtmpte") || str[0].equals("rtmps")) {
								realFileOriPath = realFileOriPath + "live=1";  //未知效果
							}
						}
						
						System.out.println(realFileOriPath);
						
						String realThumbnailPath = realThumbnailDir + "\\" + video.getId() + ".jpg"; //存放缩略图的路径
						System.out.println(realThumbnailPath);
						//FFmpeg截图控制台命令
						// 参数含义如下：
						// -y：输出文件重名的时候，自动覆盖。
						// -i：输入文件路径（可以是相对路径或者绝对路径）。
						// -ss：截取缩略图的时间点，这里是5s处。
						// -s：输出缩略图的分辨率，这里是220x110。
						// -f：输出文件格式，这里的image2代表文件格式为图片。
						// -vframes：输出视频帧的个数，这里是1。
						// 最后一个参数为输出的缩略图文件路径。
						String videoThumbnailCommand = "cmd /c start ffmpeg -y -i " + "\"" + 
														realFileOriPath + "\"" + " -ss " + 
														thumbnail_ss_cfg.getVal() + 
														" -s 305x225 -f image2 -vframes 1 " +
														"\"" + realThumbnailPath + "\"";
						System.out.println(videoThumbnailCommand);
						
						//执行命令行，新打开一个窗口执行命令，即在cmd中运行此条命令
						Process process = Runtime.getRuntime().exec(videoThumbnailCommand);  
						
						//输入输出流获取图片
						//获取二进制字节流
						BufferedInputStream in = new BufferedInputStream(process.getInputStream());
						//
						BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
						String lineStr;
						while((lineStr = inBr.readLine()) != null) {
							System.out.println(lineStr);
						}
						if (process.waitFor() != 0) {
							if( process.exitValue() == 1) { //0表示正常结束，1：非正常结束  
								System.err.println("截图失败");
							}
						}
						inBr.close();
						in.close();
						video.setThumbnailUrl(folder_thumbernail_cfg.getVal() + "/" + video.getId() + ".jpg");
						if(video.getIsLive() == 0) {
							video.setVideoState(wait_coder);
						} else {
							video.setVideoState(finished_video);
						}
						FontImage.createImage(video.getUser().getNickname(), 
								servletContext.getRealPath("/").replace('\\', '/') + "watermark/" + video.getUser().getNickname() + ".png");
						videoService.updateVideoState(video); //更新状态信息
						videoService.updateThumbnailUrl(video); //更新缩略图信息
						sleep(60 * 1000);
					}
				}
				sleep(60 * 1000);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public ServletContext getServletContext() {
		return servletContext;
	}

	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	public ConfigureService getConfigureService() {
		return configureService;
	}

	public void setConfigureService(ConfigureService configureService) {
		this.configureService = configureService;
	}

	public VideoThumbnailThread(ServletContext servletContext) {
		super();
		this.servletContext = servletContext;
	}
	public VideoThumbnailThread() {
		super();
	}
}
